package org.hfy.collections.helper;

import org.hfy.Constants;
import org.hfy.StringUtils;

import java.util.*;
import java.util.stream.Collectors;

/**
 * @Description:
 * @Author: Takagi
 * @date: 2023/4/26
 */
public class State {
    // 状态名
    public Symbol name = new Symbol();
    // 符号 : 动作
    public Map<Symbol, Action> actionTable = new HashMap<>();
    // 符号 ： 转移
    public Map<Symbol, Symbol> gotoTable = new HashMap<>();

    public Symbol getName() {
        return name;
    }

    /*
     * @Author Takagi
     * @Description: 打印状态
     * @date: 2023/4/26
     * @param symbols
     * @return
     **/
    public void showState(Set<Symbol> symbols) {
        List<String> line = this.getStateString(symbols);
        StringBuilder sb = new StringBuilder();
        for (int i = 0; i < line.size(); ++i) {
            sb.append(Constants.formatLine(line.get(i)));
            if (i < line.size() - 1) {
                sb.append("\t");
            }
        }
        System.out.println(sb);
    }

    /*
     * @Author Takagi
     * @Description: 获取状态与符号对应的动作与转换
     * @date: 2023/4/27
     * @param symbols
     * @return * @return List<String>
     **/
    public List<String> getStateString(Set<Symbol> symbols) {
        Set<Symbol> terminators = symbols.stream().filter(Constants::isTerminator).collect(Collectors.toSet());
        Set<Symbol> nonTerminators = symbols.stream().filter(Constants::isNonTerminator).collect(Collectors.toSet());
        List<String> line = new LinkedList<>();
        line.add(this.name.toString());
        line.addAll(terminators.stream()
                .map(key -> Optional.ofNullable(actionTable.get(key)).map(Object::toString).orElse(""))
                .collect(Collectors.toList()));
        line.addAll(nonTerminators.stream()
                .map(key -> Optional.ofNullable(gotoTable.get(key)).map(StringUtils::extractNumbers).orElse(""))
                .collect(Collectors.toList()));
        return line;
    }


    /*
     * @Author Takagi
     * @Description: 设置状态名
     * @date: 2023/4/26
     * @param name
     * @return
     **/
    public void setName(String name) {
        this.name = new Symbol(name);
    }

    /*
     * @Author Takagi
     * @Description: 设置状态名
     * @date: 2023/4/26
     * @param name
     * @return
     **/
    public void setName(int name) {
        this.name = new Symbol(Integer.toString(name));
    }

    /*
     * @Author Takagi
     * @Description: 设置移进动作
     * @date: 2023/4/26
     * @param input
     * @param state
     * @return
     **/
    public void setShiftAction(Symbol input, String state) {
        Action action = new Action();
        action.actionType = new Symbol(Constants.SHIFT_ACTION);
        action.stateNo = new Symbol(state);
        this.actionTable.put(input, action);
    }

    public void setShiftAction(Symbol input, int state) {
        Action action = new Action();
        action.actionType = new Symbol(Constants.SHIFT_ACTION);
        action.stateNo = new Symbol(Integer.toString(state));
        this.actionTable.put(input, action);
    }

    /*
     * @Author Takagi
     * @Description: 设置归约动作
     * @date: 2023/4/26
     * @param input
     * @param productionNo
     * @param production
     * @return
     **/
    public void setReduceAction(Symbol input, Integer productionNo, Production production) {
        Action action = new Action();
        action.actionType = new Symbol(Constants.REDUCTION_ACTION);
        action.productionNo = new Symbol(productionNo.toString());
        action.production = production;
        this.actionTable.put(input, action);
    }


    /*
     * @Author Takagi
     * @Description: 设置 接受 动作
     * @date: 2023/4/26
     * @param input
     * @return
     **/
    public void setAcceptAction(Symbol input) {
        Action action = new Action();
        action.actionType = new Symbol(Constants.REDUCTION_ACTION);
        action.accept = true;
        this.actionTable.put(input, action);
    }

    /*
     * @Author Takagi
     * @Description: 设置转移表
     * @date: 2023/4/26
     * @param input
     * @param state
     * @return
     **/
    public void setGoto(Symbol input, String state) {
        this.gotoTable.put(input, new Symbol(state));
    }

    public void setGoto(Symbol input, int state) {
        this.gotoTable.put(input, new Symbol(Integer.toString(state)));
    }

    /*
     * @Author Takagi
     * @Description: 获取动作
     * @date: 2023/4/26
     * @param input
     * @return * @return Action
     **/
    public Action getAction(Symbol input) {
        return this.actionTable.get(input);
    }

    /*
     * @Author Takagi
     * @Description: 获取转移
     * @date: 2023/4/26
     * @param input
     * @return * @return Symbol
     **/
    public Symbol getGoto(Symbol input) {
        return this.gotoTable.get(input);
    }

    @Override
    public String toString() {
        return this.name.toString();
    }
}
